package com.example.qxfw.ldyj.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dmgis.service.DmServiceConnector;
import com.example.qxfw.backgroundManagement.service.WorkforceManagementService;
import com.example.qxfw.common.entity.xt.SysConfig;
import com.example.qxfw.common.entity.zy.BaseProduct;
import com.example.qxfw.common.entity.zy.ThunderFcst;
import com.example.qxfw.common.service.impl.FileRequestService;
import com.example.qxfw.common.util.DateUtil;
import com.example.qxfw.common.util.DocxUtil;
import com.example.qxfw.common.util.FileUtil;
import com.example.qxfw.ldyj.mapper.ThunderFcstMapper;
import com.example.qxfw.ldyj.service.QsybSevice;
import com.example.qxfw.mongodb.hy.entity.HyDocFile;
import com.example.qxfw.mongodb.hy.entity.HyImageFile;
import com.example.qxfw.mongodb.hy.entity.HyPdfFile;
import com.example.qxfw.mongodb.hy.service.DocFileService;
import com.example.qxfw.mongodb.hy.service.HyImageFileService;
import com.example.qxfw.mongodb.hy.service.PdfFileService;
import com.example.qxfw.qxxx.service.IssuerInfoService;
import com.example.qxfw.rcyw.pojo.JobMake;
import com.example.qxfw.ybzz.mapper.BaseProductMapper;
import com.example.qxfw.ybzz.service.BaseProductService;
import com.example.qxfw.ybzz.service.SysConfigService;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.io.*;
import java.sql.Timestamp;
import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.example.qxfw.common.util.DocxUtil.replaceTextInParagraph;
import static java.lang.System.out;

@Service
public class QsybSeviceImpl implements QsybSevice {
    @Autowired
    private ThunderFcstMapper thunderFcstMapper;

    @Autowired
    private DocFileService docFileService;

    @Autowired
    private PdfFileService pdfFileService;

    @Autowired
    private HyImageFileService hyImageFileService;

    @Autowired
    private WorkforceManagementService workforceManagementService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private BaseProductMapper baseProductMapper;

    @Autowired
    private IssuerInfoService issuerInfoService;

    @Autowired
    private BaseProductService baseProductService;

    @Qualifier("mongoSecondTemplate")
    @Autowired
    private MongoTemplate mongoTemplate;

    @Value("${county}")
    private String m_county;

    @Value("${dmgis.ip}")
    private String serverIp;

    @Value("${dmgis.port}")
    private String port;

    @Value("${dmgis.serName}")
    private String serverName;

    @Value("${dmgis.image_url}")
    private String image_url;


    FileRequestService ms = new FileRequestService();

    @Override
    public List<ThunderFcst> selectByReporttimeAndForecasttimeAndForecastntimesOfThunderFcst(
            Timestamp reporttime, String forecasttime, Short forecastntimes) {
        return thunderFcstMapper.selectList(new LambdaQueryWrapper<ThunderFcst>()
                .eq(reporttime != null, ThunderFcst::getReporttime, reporttime)
                .eq(StringUtils.isNotBlank(forecasttime), ThunderFcst::getForecasttime, forecasttime)
                .eq(forecastntimes != 0, ThunderFcst::getForecastntimes, forecastntimes));
    }

    @Override
    public void createDoc(List<ThunderFcst> list, String filename, String time, String forecasttime, Short forecastntimes, String number, String maker) throws ParseException {
        //签发人
        List<String> issuers = issuerInfoService.getUserName1("2");

        ApplicationHome applicationHome = new ApplicationHome(FileUtil.class);
        String resourcePath = "";
        resourcePath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() + "\\src\\main\\resources\\Documents\\雷电气象\\雷电潜势预报模板.docx";
        String targetPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() + "\\src\\main\\resources\\temp\\" + filename + ".docx";
        String pdfTargetPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() + "\\src\\main\\resources\\temp\\" + filename + ".pdf";
        String[] placeholders = new String[]{"[0]", "[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]", "[9]", "[10]", "[市]", "[签发人2]"};
        List<String> replacements = new ArrayList<>();
        replacements.add(time.substring(0, 4));
        replacements.add(number);
        replacements.add(time);
        replacements.add(forecasttime);
        replacements.add(com.dmgis.util.DateTime.parseDate(time).AddHours(Integer.parseInt(forecasttime) + forecastntimes).toDateString());
        replacements.add(com.dmgis.util.DateTime.parseDate(time).AddHours(Integer.parseInt(forecasttime) + forecastntimes).toDateTimeString("HH"));

        double valueMax = -10000.0;
        String strText = "";//清空
        String strtext = "";
        double sss = 0.0;
        int sum = 0;
        for (ThunderFcst obj : list) {
            if (obj.getTown().contains("凌云"))
            {
                sss += obj.getPredictprobability();
                if (obj.getPredictlevel().equals("强"))
                    valueMax = valueMax > 4 ? valueMax : 4;
                else if (obj.getPredictlevel().equals("中"))
                    valueMax = valueMax > 3 ? valueMax : 3;
                else if (obj.getPredictlevel().equals("弱"))
                    valueMax = valueMax > 2 ? valueMax : 2;
                else if (obj.getPredictlevel().equals("无"))
                    valueMax = valueMax > 1 ? valueMax : 1;
                sum++;
            }

            if (obj.getPredictlevel().equals("强")) {
                if (!strText.contains(obj.getTown())) {
                    strText += obj.getTown() + "、";
                }
            }
            if (obj.getPredictlevel().equals("中")) {
                if (!strText.contains(obj.getTown())) {
                    strText += obj.getTown() + "、";
                }
            }
        }
        if (strText != "") {
            strtext = "发生雷电可能性较大的地区主要出现在";

            strtext = strText.substring(0, strtext.length() - 1) + "等地，";
        }
        double dveg = 0;
        if (sum != 0)
            dveg = sss / sum * 100;
        String strdveg = String.valueOf(dveg);
        if (strdveg.length() > 5)
            strdveg = strdveg.substring(0, 5);
        switch ((int) valueMax) {
            case 2:
                replacements.add("黄色");
                break;
            case 3:
                replacements.add("橙色");
                break;
            case 4:
                replacements.add("红色");
                break;
            default:
                replacements.add("蓝色");
                break;
        }

        replacements.add(strtext);//7
        replacements.add(strdveg + "%");//8
        replacements.add(time);//9
        replacements.add(maker);//10
        replacements.add(m_county);//市
        replacements.add(issuers.size() > 0 ? issuers.get(0) : "");

        String radinSrvLanguage = "";
        List<SysConfig> sysList = sysConfigService.getServiceLanguage();
        if (sysList.size() > 0) {
            for (int i = 0; i < sysList.size(); i++) {
                if (sysList.get(i).getParamname().contains("潜势预报")) {
                    radinSrvLanguage = sysList.get(i).getParamvalue().trim();
                }
            }
        }

        String context = radinSrvLanguage.replace("[概率]", replacements.get(6));
        context = context.replace("[发布日期]", com.dmgis.util.DateTime.parseDate(time).toDateTimeString("yyyy年MM月dd日HH时"));
        context = context.replace("[时效]", "未来" + forecastntimes + "小时");

        Timestamp timestampMake = DateUtil.localDateTimeToTimestamp(LocalDateTime.now());
        // forecasttime
        LocalDate currentDate = LocalDate.now();
        Timestamp timestampForcast = DateUtil.localDateTimeToTimestamp(currentDate.atStartOfDay());
        // 先获取表中是否已经又生成好的数据，有就直接查询将查询的结果返回，无则生成。
        List<BaseProduct> baseProducts = baseProductMapper.selectList(Wrappers.<BaseProduct>lambdaQuery().eq(BaseProduct::getProductname, filename).eq(BaseProduct::getProducttype, "潜势预报"));
        if (baseProducts != null && baseProducts.size() > 0) {
            // 获取mongo库里的文档
            //HyDocFile hyDocFile = docFileService.getByTableId(String.valueOf(baseProducts.get(0).getId()));
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", String.valueOf(baseProducts.get(0).getId()));
            map.put("tableName", "base_product");
            map.put("collectionName", "doc_file");
            byte[] hyDocFile = ms.selectData(map);

            // 如果文档存在就直接返回查询结果
            if (hyDocFile != null) {
                //docFileService.deleteById(String.valueOf(baseProducts.get(0).getId()));
                HashMap<String, Object> map1 = new HashMap<>();
                map.put("id", String.valueOf(baseProducts.get(0).getId()));
                map.put("tableName", "base_product");
                map.put("collectionName", "doc_file");
                long h = ms.deleteData(map);
                // 如果表中有信息，文档不存在或表中无信息，就新生成一个文档并删除这条数据
                int i = baseProductMapper.deleteById(baseProducts.get(0).getId());
                //签发人
                InsertBaseProduct(list, filename, timestampForcast, timestampMake,
                        resourcePath, targetPath, placeholders, replacements, pdfTargetPath, context);
            } else {
                // 如果表中有信息，文档不存在或表中无信息，就新生成一个文档并删除这条数据
                int i = baseProductMapper.deleteById(baseProducts.get(0).getId());
                InsertBaseProduct(list, filename, timestampForcast, timestampMake,
                        resourcePath, targetPath, placeholders, replacements, pdfTargetPath, context);
            }
        } else {
            // 文档信息，先存入表agri_product
            InsertBaseProduct(list, filename, timestampForcast, timestampMake,
                    resourcePath, targetPath, placeholders, replacements, pdfTargetPath, context);
        }
        JobMake jobMake = new JobMake();
        jobMake.setJobname("雷暴趋势预报");
        jobMake.setNametype("雷电气象");
        jobMake.setRecentmaketime(DateTime.now());
        workforceManagementService.updateJobMark2(jobMake);
        String paramName = "dm_qsybqh";
        SysConfig config = new SysConfig();
        config.setParamname(paramName);
        config.setParamvalue(String.valueOf(Integer.parseInt(number) + 1));
        sysConfigService.updateByParamName(config);
    }

    /**
     * 入库
     *
     * @param filename         文件名
     * @param timestampForcast
     * @param timestampMake
     * @param resourcePath
     * @param targetPath
     * @param placeholders
     * @param replacements
     * @param pdfTargetPath
     */
    private Object InsertBaseProduct(List<ThunderFcst> list, String filename, Timestamp timestampForcast,
                                     Timestamp timestampMake, String resourcePath, String targetPath,
                                     String[] placeholders, List<String> replacements, String pdfTargetPath, String context) {

        try (
                //申请资源
                FileInputStream templateStream = new FileInputStream(resourcePath);
                XWPFDocument document = new XWPFDocument(templateStream);
                FileOutputStream targetSteam = new FileOutputStream(targetPath);
                ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream();
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

            String imgpath = "";//图片路径

            List<XWPFParagraph> paragraphs = document.getParagraphs();
            // 替换段落内容
            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                //获取段落内容
                String text = paragraph.getText();

                //替换文字内容
                replaceTextInParagraph(paragraph, placeholders, replacements.toArray(new String[replacements.size()]));

                //插入图片
                if (text.contains("[图1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFParagraph newPara = document.insertNewParagraph(cursor);
                    newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                    XWPFRun newParaRun = newPara.createRun();

                    Instant instant = Instant.ofEpochMilli(timestampForcast.getTime());
                    ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时");
                    String formattedDate = zonedDateTime.format(formatter);

                    DmServiceConnector conn = new DmServiceConnector(serverIp, port);
                    //返回等值图点集json的插件服务
                    String callPlugin = conn.getCallPlugin("model", "makepic", serverName + "|2|" + m_county + "潜势预报分析图|" + formattedDate + "发布|dzmLD");
                    out.println(callPlugin);

                    if (StringUtils.isNotBlank(callPlugin)) {
                        String filepath = "http://" + image_url + callPlugin;
                        imgpath = filepath;
                        InputStream inputStream = FileUtil.getNetFile(filepath);
                        //插入图片
                        newParaRun.addPicture(inputStream, XWPFDocument.PICTURE_TYPE_PNG, "image.png,", Units.toEMU(300), Units.toEMU(380));
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入实况数据表格
                if (list.size() > 0 && text.contains("[表1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //添加表头
                    XWPFTableRow row_0 = table.getRow(0);
                    row_0.getCell(0).setText("区县");
                    row_0.addNewTableCell().setText("乡镇");
                    row_0.addNewTableCell().setText("预报等级");
                    row_0.addNewTableCell().setText("预测概率");
                    list.forEach(sk -> {
                        XWPFTableRow dataRow = table.createRow();
                        dataRow.getCell(0).setText(sk.getCounty());
                        dataRow.getCell(1).setText(sk.getTown());
                        dataRow.getCell(2).setText(sk.getPredictlevel());
                        dataRow.getCell(3).setText(String.valueOf(sk.getPredictprobability()));
                    });
                    setTableLocation(table, "center");
                    setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
            }
            // 将生成的文档保存到输出文件
            document.write(targetSteam);
            targetSteam.close();

            // 设置前端响应
            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            //查询是否入库

            int productid = 0;
            List<BaseProduct> list2 = baseProductMapper.selectList(Wrappers.<BaseProduct>lambdaQuery().eq(BaseProduct::getProductname, filename).eq(BaseProduct::getProducttype, "潜势预报"));
            if (list2.size() != 0) {
                productid = list2.get(0).getId();
                //pg已入库，存入mongo库
                // HyDocFile hyDocFile = new HyDocFile();
                // hyDocFile.setData(byteArray);
                // hyDocFile.setTable_name("base_product");
                // hyDocFile.setId(String.valueOf(list2.get(0).getId()));
                // mongoTemplate.save(hyDocFile);
                HashMap<String, Object> map = new HashMap<>();
                map.put("id", list2.get(0).getId());
                map.put("data", byteArray);
                map.put("table_name", "base_product");
                map.put("collectionName", "doc_file");
                ms.insertData(map);


            } else {
                //先存入pg库
                BaseProduct baseProduct = new BaseProduct();
                baseProduct.setForecasttime(timestampForcast);
                baseProduct.setMaketime(timestampMake);
                baseProduct.setMaker(replacements.get(10));
                baseProduct.setContext(context);
                baseProduct.setProductname(filename);
                baseProduct.setProducttype("潜势预报");
                baseProductService.save(baseProduct);
                productid = baseProduct.getId();
                //存入mongo库
                // HyDocFile hyDocFile = new HyDocFile();
                // hyDocFile.setData(byteArray);
                // hyDocFile.setTable_name("base_product");
                // hyDocFile.setId(String.valueOf(baseProduct.getId()));
                // mongoTemplate.save(hyDocFile);
                HashMap<String, Object> map = new HashMap<>();
                map.put("id", baseProduct.getId());
                map.put("data", byteArray);
                map.put("table_name", "base_product");
                map.put("collectionName", "doc_file");
                ms.insertData(map);
            }
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", filename + ".docx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);

            DocxUtil.wordToPdf(targetPath, pdfTargetPath);
            //文件保存入数据库
            //HyPdfFile pdffile = new HyPdfFile();
            byte[] bytes = new byte[0];
            try {
                bytes = DocxUtil.readDocxFileToByteArray(pdfTargetPath);
                //pdffile.setData(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // pdffile.setId(String.valueOf(productid));
            // pdffile.setTable_name("base_product");
            // pdffile.setName(filename + ".pdf");
            // pdfFileService.save(pdffile);
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", productid);
            map.put("data", bytes);
            map.put("table_name", "base_product");
            map.put("collectionName", "pdf_file");
            ms.insertData(map);

            // HyImageFile hyImageFile = new HyImageFile();
            // hyImageFile.setTable_name("base_product");
            // hyImageFile.setData(FileUtil.getBytesByFile(imgpath));
            // hyImageFile.setId(String.valueOf(productid));
            // hyImageFileService.save(hyImageFile);
            InputStream inputStream2 = FileUtil.getNetFile(imgpath);
            byte[] buffer2 = new byte[1024];
            int bytesRead2;
            while ((bytesRead2 = inputStream2.read(buffer2)) != -1) {
                byteArrayOutputStream2.write(buffer2, 0, bytesRead2);
            }
            byte[] bytes2 = byteArrayOutputStream2.toByteArray();
            HashMap<String, Object> map2 = new HashMap<>();
            map2.put("id", productid);
            map2.put("data", bytes2);
            map2.put("table_name", "base_product");
            map2.put("collectionName", "image_file");
            map2.put("advCode", "451027");
            ms.insertData(map2);

            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);

        } catch (FileNotFoundException ex) {
            throw new RuntimeException(ex);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

    }


    /**
     * 设置单元格水平位置和垂直位置
     *
     * @param xwpfTable
     * @param verticalLoction    单元格中内容垂直上TOP，下BOTTOM，居中CENTER，BOTH两端对齐
     * @param horizontalLocation 单元格中内容水平居中center,left居左，right居右，both两端对齐
     */
    public static void setCellLocation(XWPFTable xwpfTable, String verticalLoction, String horizontalLocation) {
        List<XWPFTableRow> rows = xwpfTable.getRows();
        for (XWPFTableRow row : rows) {
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                CTTc cttc = cell.getCTTc();
                CTP ctp = cttc.getPList().get(0);
                CTPPr ctppr = ctp.getPPr();
                if (ctppr == null) {
                    ctppr = ctp.addNewPPr();
                }
                CTJc ctjc = ctppr.getJc();
                if (ctjc == null) {
                    ctjc = ctppr.addNewJc();
                }
                ctjc.setVal(STJc.Enum.forString(horizontalLocation)); //水平居中
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf(verticalLoction));//垂直居中
            }
        }
    }

    /**
     * 设置表格位置
     *
     * @param xwpfTable
     * @param location  整个表格居中center,left居左，right居右，both两端对齐
     */
    public static void setTableLocation(XWPFTable xwpfTable, String location) {
        CTTbl cttbl = xwpfTable.getCTTbl();
        CTTblPr tblpr = cttbl.getTblPr() == null ? cttbl.addNewTblPr() : cttbl.getTblPr();
        CTJc cTJc = tblpr.addNewJc();
        cTJc.setVal(STJc.Enum.forString(location));
    }
}
